/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package gcalscraper.wapo;

import java.io.InputStream;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import nu.xom.Builder;
import nu.xom.Document;
import nu.xom.Node;
import nu.xom.Nodes;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.params.ClientPNames;
import org.apache.http.client.params.CookiePolicy;
import org.apache.http.impl.client.DefaultHttpClient;
import org.xml.sax.XMLReader;

/**
 *
 * @author dave
 */
public class PageWorker extends Thread {
  private Set<Integer> finishedPages;
  private List<Integer> pageWorkQueue;
  private List<Event> detailWorkQueue;
  private List<Event> events;
  
  private boolean done;  
  
  private Logger logger;
  
  private DefaultHttpClient httpClient;
  private Builder builder;

  private PageWorkerListener ell;
  
  public PageWorker(List<Integer> pageWorkQueue, 
      List<Event> events,
      Set<Integer> finishedPages,
      List<Event> detailWorkQueue,
      PageWorkerListener ell) {
    this.finishedPages = finishedPages;
    this.pageWorkQueue = pageWorkQueue;
    this.detailWorkQueue = detailWorkQueue;
    this.events = events;
    this.ell = ell;
    
    logger = Logger.getAnonymousLogger();
    
    httpClient = new DefaultHttpClient();
    httpClient.getParams().setParameter(
            ClientPNames.COOKIE_POLICY, CookiePolicy.BROWSER_COMPATIBILITY);
    
    XMLReader tagsoup = new org.ccil.cowan.tagsoup.Parser(); 
    try {
      tagsoup.setFeature(
          "http://xml.org/sax/features/namespaces", false);
      tagsoup.setFeature(
          "http://xml.org/sax/features/namespace-prefixes", false);
    } catch (Exception ex) {
      logger.log(Level.SEVERE, "Trouble with tagsoup namespace settings", ex);
    }
    builder = new Builder(tagsoup);
  }

  @Override
  public void run() {
    while (!done) {
      Integer toDo = null;
      synchronized (pageWorkQueue) {
        if (pageWorkQueue.size() > 0) {
          toDo = pageWorkQueue.remove(0);
        } else {
          try {
            pageWorkQueue.wait();
          } catch (Exception ex) {
            logger.log(Level.WARNING, "Page worker interrupted!", ex);
          }
        }        
      }
      if (toDo != null) 
        workOnPage(toDo);
    }
  }  
  
  public void workOnPage(Integer pageNumber) { 
    System.out.print("P");
    ell.startPage(pageNumber);
    try {
      synchronized(finishedPages) {
        finishedPages.add(pageNumber);
      }
      String url = getPageUrl(pageNumber);
      //logger.info("Getting " + url);
      HttpGet httpget = new HttpGet(url);

      HttpResponse response = httpClient.execute(httpget);
      HttpEntity entity = response.getEntity();
      InputStream is = entity.getContent();
      
      //logger.info("Got page, building DOM..");
      
      Document doc = builder.build(is);
      
      /*Serializer serializer = new Serializer(System.out, "ISO-8859-1");
      serializer.setIndent(2);
      serializer.write(doc);*/
      
      Nodes nodes = doc.query("//td[@class='res_num']/ancestor::td");
      for (int i = 1; i < nodes.size(); i++) {
        Node n = nodes.get(i);
        Event newEvent = new Event(n);        
        synchronized(detailWorkQueue) {
          detailWorkQueue.add(newEvent);
          detailWorkQueue.notifyAll();
        }
        synchronized(events) {
          events.add(newEvent);
        }
      }      
      
      Nodes morePages = doc.query("//td[@class='page_num']/a[contains(@onclick, 'goto')]");
      for (int i = 0; i < morePages.size(); i++) {
        String p = morePages.get(i).getValue();
        Integer nextPage = null;
        try {
          nextPage = Integer.parseInt(p);          
        } catch (Exception ex) {
        }
        
        if (nextPage != null) {
          synchronized (finishedPages) {
            synchronized (pageWorkQueue) {
              if (!finishedPages.contains(nextPage)) {
                finishedPages.add(nextPage);
                pageWorkQueue.add(nextPage);
                pageWorkQueue.notifyAll();
              }
            }
          }
        }
      }
      
      /*Nodes nexts = doc.query("//td[@class='page_num']/a/b[contains(text(),'Next')]");
      keepGoing = nexts.size() > 0;*/
    } catch (Exception ex) {
      logger.log(Level.SEVERE, "Error getting page " + pageNumber, ex);
    }   
    ell.stopPage(pageNumber);
  }
  
  public String getPageUrl(Integer page) {
    return "http://www.washingtonpost.com/ac2/wp-dyn/CGSearch"
        + "?displaySearchTerm=&displaySearchLocation=&currentPage=" + page 
        + "&sa=newPage&sortBy=106&displayDistance=0.0&f_group=%5EEvents%24"
        + "&nameSelection=-+Select+-";
  }

  public void setDone(boolean done) {
    this.done = done;
  }
}
